using System.Web.Mvc;
using GoldenBicycleCompany.Core;
using SharpArch.Core.PersistenceSupport;
using SharpArch.Core.DomainModel;
using System.Collections.Generic;
using System;
using SharpArch.Web.NHibernate;
using NHibernate.Validator.Engine;
using System.Text;
using SharpArch.Web.CommonValidator;
using SharpArch.Core;

namespace GoldenBicycleCompany.Web.Controllers
{
    [HandleError]
    public class RentalsController : Controller
    {
        public RentalsController(IRepository<Rental> rentalRepository) {
            Check.Require(rentalRepository != null, "rentalRepository may not be null");

            this.rentalRepository = rentalRepository;
        }

        [Transaction]
        public ActionResult Index() {
            IList<Rental> rentals = rentalRepository.GetAll();
            return View(rentals);
        }

        [Transaction]
        public ActionResult Show(int id) {
            Rental rental = rentalRepository.Get(id);
            return View(rental);
        }

        public ActionResult Create() {
            RentalFormViewModel viewModel = RentalFormViewModel.CreateRentalFormViewModel();
            return View(viewModel);
        }

        [ValidateAntiForgeryToken]
        [Transaction]
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Create(Rental rental) {
            if (ViewData.ModelState.IsValid && rental.IsValid()) {
                rentalRepository.SaveOrUpdate(rental);

                TempData[ControllerEnums.GlobalViewDataProperty.PageMessage.ToString()] = 
                    "The rental was successfully created.";
                return RedirectToAction("Index");
            }

            RentalFormViewModel viewModel = RentalFormViewModel.CreateRentalFormViewModel();
            viewModel.Rental = rental;
            return View(viewModel);
        }

        [Transaction]
        public ActionResult Edit(int id) {
            RentalFormViewModel viewModel = RentalFormViewModel.CreateRentalFormViewModel();
            viewModel.Rental = rentalRepository.Get(id);
            return View(viewModel);
        }

        [ValidateAntiForgeryToken]
        [Transaction]
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Edit(Rental rental) {
            Rental rentalToUpdate = rentalRepository.Get(rental.Id);
            TransferFormValuesTo(rentalToUpdate, rental);

            if (ViewData.ModelState.IsValid && rental.IsValid()) {
                TempData[ControllerEnums.GlobalViewDataProperty.PageMessage.ToString()] = 
                    "The rental was successfully updated.";
                return RedirectToAction("Index");
            }
            else {
                rentalRepository.DbContext.RollbackTransaction();

                RentalFormViewModel viewModel = RentalFormViewModel.CreateRentalFormViewModel();
                viewModel.Rental = rental;
                return View(viewModel);
            }
        }

        private void TransferFormValuesTo(Rental rentalToUpdate, Rental rentalFromForm) {
            rentalToUpdate.ChangeCustomer(rentalFromForm.Customer);
            rentalToUpdate.AddBicycles(rentalFromForm.Bicycles as IList<Bicycle>);
            rentalToUpdate.ChangeActualDropOffDateTime(rentalFromForm.ActualDropOffDateTime);
            rentalToUpdate.ChangePickUpDateTime(rentalFromForm.PickUpDateTime);
            rentalToUpdate.ChangeRequestedDropOffDateTime(rentalFromForm.RequestedDropOffDateTime);
            rentalToUpdate.ChangeLateness(rentalFromForm.IsLate);
            rentalToUpdate.ChangeCustomerNotifiedWillBeLate(rentalFromForm.NotifiedWillBeLate);
        }

        [ValidateAntiForgeryToken]
        [Transaction]
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Delete(int id) {
            string resultMessage = "The rental was successfully deleted.";
            Rental rentalToDelete = rentalRepository.Get(id);

            if (rentalToDelete != null) {
                rentalRepository.Delete(rentalToDelete);

                try {
                    rentalRepository.DbContext.CommitChanges();
                }
                catch {
                    resultMessage = "A problem was encountered preventing the rental from being deleted. " +
                        "Another item likely depends on this rental.";
                    rentalRepository.DbContext.RollbackTransaction();
                }
            }
            else {
                resultMessage = "The rental could not be found for deletion. It may already have been deleted.";
            }

            TempData[ControllerEnums.GlobalViewDataProperty.PageMessage.ToString()] = resultMessage;
            return RedirectToAction("Index");
        }

        /// <summary>
        /// Holds data to be passed to the Rental form for creates and edits
        /// </summary>
        public class RentalFormViewModel
        {
            private RentalFormViewModel() { }

            /// <summary>
            /// Creation method for creating the view model. Services may be passed to the creation 
            /// method to instantiate items such as lists for drop down boxes.
            /// </summary>
            public static RentalFormViewModel CreateRentalFormViewModel() {
                RentalFormViewModel viewModel = new RentalFormViewModel();
                
                return viewModel;
            }

            public Rental Rental { get; internal set; }
        }

        private readonly IRepository<Rental> rentalRepository;
    }
}
